import java.awt.geom.AffineTransform;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.PathIterator;
import java.awt.geom.Point2D;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.HashMap;
import java.util.TreeMap;

public class MapFileManager {
	private HashMap<Integer, Road> roadPoints;
	private DiGraph roadGraph; 

	public MapFileManager() {
		roadPoints = new HashMap<Integer, Road>();
		roadGraph = new DiGraph();
	}

	public DiGraph getRoadGraph() {
		return roadGraph;
	}
	
	/**
	 * Testing main thread for loading saving and animation threads
	 * @param args
	 */
	public static void main(String[] args) {
		MapFileManager load = new MapFileManager();

		try {
			Calendar now = Calendar.getInstance();
			long time = now.getTimeInMillis();

			TreeMap<String, Road> roads = load.loadRoads("Road2.txt", "\\|");
			TreeMap<String, Area> suburbs = load.loadSuburbs("Suburb1.txt", "\\|");
			
			MovableTransport move = new MovableTransport(roads);
			
			Thread t = new Thread(move);
			t.start();

			//load.saveSuburbs(suburbs, "SuburbsNew.txt", "\\|");
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	
	/**
	 * 
	 * @param filename
	 * @throws IOException
	 */
	public TreeMap<String, Road> loadRoads(String filename, String delimiter) throws IOException {
		TreeMap<String, Road> roadMap = new TreeMap<String, Road>();
		
		FileInputStream fstream = new FileInputStream(filename);
		DataInputStream in = new DataInputStream(fstream);
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String strLine = br.readLine();

		while (!strLine.equalsIgnoreCase("finalend")) {
			String[] split = strLine.split("\\|");
			Road road = new Road(split[0]);
			
			road.setType(Integer.parseInt(split[5]));
			road.setLanes(Integer.parseInt(split[6]));

			while (!strLine.equalsIgnoreCase("end")) {
				Point2D.Double p1 = new Point2D.Double(
						java.lang.Double.parseDouble(split[1]),
						java.lang.Double.parseDouble(split[2]));

				Point2D.Double p2 = new Point2D.Double(
						java.lang.Double.parseDouble(split[3]),
						java.lang.Double.parseDouble(split[4]));

				road.addSection(new Line2D.Double(p1, p2));
				road.append(p1, p2);
				roadPoints.put(p1.hashCode(), road);
				roadPoints.put(p2.hashCode(), road);

				if (roadGraph.getVertex(p1) == null)
					roadGraph.createVertex(p1);
				if (roadGraph.getVertex(p2) == null)
					roadGraph.createVertex(p2);
				
				roadGraph.addEdge(roadGraph.getVertex(p1), roadGraph.getVertex(p2), road.getWeight());
				roadGraph.addEdge(roadGraph.getVertex(p2), roadGraph.getVertex(p1), road.getWeight());
				
				strLine = br.readLine();
				split = strLine.split("\\|");
			}
			
			roadMap.put(road.getName(), road);
			strLine = br.readLine();
		}

		return roadMap;
	}

	
	/**
	 * 
	 * @param filename
	 * @throws IOException
	 */
	public TreeMap<String, Area> loadSuburbs(String filename, String delimiter) throws IOException {
		TreeMap<String, Area> suburbs = new TreeMap<String, Area>();
		
		Point2D.Double current = null;

		FileInputStream fstream = new FileInputStream(filename);
		DataInputStream in = new DataInputStream(fstream);
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		String strLine = br.readLine();

		while (!strLine.equalsIgnoreCase("finalend")) {
			String[] parts = strLine.split(delimiter);
			Area suburb = new Area(parts[0], delimiter);
			while (!strLine.equalsIgnoreCase("end")) {

				if (parts.length > 1) {

					double x = java.lang.Double.parseDouble(parts[1]);
					double y = java.lang.Double.parseDouble(parts[2]);
					current = new Point2D.Double(x, y);

					//suburb.addPoint(suburb.getName(),current);	
					suburb.addPoint(current);
				}
				strLine = br.readLine();
				parts = strLine.split(delimiter);
			}

			// Join the first and last points of the suburb
			suburbs.put(suburb.getName(), suburb);
			strLine = br.readLine();
			//System.out.println(strLine);
		}
		
		//System.out.println("Suburb count \t: " + suburbs.size());
		return suburbs;
	}
	
	public void saveState(TreeMap<String, State> states, String filename, String delimiter) throws IOException
	{
		FileWriter out = new FileWriter(filename);
		
		AffineTransform tran =  new AffineTransform();
		
		for (State state : states.values()) {
			
			Path2D.Double d = state.getDrawPath();
			Point2D point = d.getCurrentPoint();
			PathIterator path = d.getPathIterator(tran);
			
			while(path.isDone() == false){
				String[] name = state.getName().split("\\|"); 
				double[] latlong = new double[2];
				path.currentSegment(latlong);
				String line = "";
				line = line.concat(name[0] +""+delimiter);
				line = line.concat((int)latlong[0] +""+ delimiter);
				line = line.concat(java.lang.Integer.toString((int)latlong[1]));
				line = line.concat("\n");
				out.write(line);
				path.next();
			}
	
			out.write("end\n");
		}
	
		out.write("finalend");
		out.close();
		
	}
	
	
	public void saveSuburbs(TreeMap<String, Area> suburbs, String filename, String delimiter) throws IOException 
	{
		FileWriter out = new FileWriter(filename);
		
		for (Area suburb : suburbs.values()) {
			for (Point2D.Double pt : suburb.getPoints()) {
				String line = "";
				line = line.concat(suburb.getName() +""+ delimiter);
				line = line.concat(pt.x + ""+delimiter);
				line = line.concat(java.lang.Double.toString(pt.y));
				line = line.concat("\n");
				out.write(line);
			}
			out.write("end\n");
		}
		out.write("finalend");
		out.close();
	}
	
	public void saveRails(TreeMap<String, Rail> rails, String filename, String delimiter) throws IOException {
		FileWriter out = new FileWriter(filename);
		
		AffineTransform tran =  new AffineTransform();
		
		for (Rail rail : rails.values()) {
			
			Path2D.Double d = rail.getDrawPath();
			Point2D point = d.getCurrentPoint();
			PathIterator path = d.getPathIterator(tran);
			
			while(path.isDone() == false){
				String[] name = rail.getName().split("\\|"); 
				double[] latlong = new double[2];
				path.currentSegment(latlong);
				String line = "";
				line = line.concat(name[0] +""+delimiter);
				line = line.concat(latlong[0] +""+ delimiter);
				line = line.concat(java.lang.Integer.toString((int)latlong[1]));
				line = line.concat("\n");
			//	line = line.concat("hello");
				out.write(line);
				path.next();
			}
	
			out.write("end\n");
		}
	
		out.write("finalend");
		out.close();
	}
	
	
	public void saveRoads(TreeMap<String, Road> roads, String filename, String delimiter) throws IOException {
		FileWriter out = new FileWriter(filename);
		AffineTransform tran =  new AffineTransform();
		
		for (Road road : roads.values()) 
		{
			Path2D.Double d = road.getDrawPath();
			Point2D point = d.getCurrentPoint();
			PathIterator path = d.getPathIterator(tran);
			
			for(Line2D.Double e : road.getSections()){
				
				String line = "";
				line = line.concat(road.getName() +""+delimiter);
				line = line.concat((int)e.x1 +""+ delimiter);
				line = line.concat((int)e.y1 +""+ delimiter);
				line = line.concat((int)e.x2 +""+ delimiter);
				line = line.concat((int)e.y2 +""+ delimiter);
				line = line.concat(road.getType() + "" + delimiter);
				line = line.concat(java.lang.Integer.toString(road.getLanes()));
				
				line = line.concat("\n");
				out.write(line);
			}
		
			out.write("end\n");
		}
		out.write("finalend");
		out.close();
	}
	
	
	public void createSCNFile(String filename, String[] filenames, String delimiter)throws IOException
	{
		
		FileWriter out = new FileWriter(filename);
		String line = "";
		line = line.concat("State" + "," + filenames[0] +"," + delimiter +"\n");
		line = line.concat("Area" + "," + filenames[1] +","+ delimiter +"\n");
		line = line.concat("Road" + "," + filenames[2] + "," + delimiter + "\n");
		line = line.concat("Rail" + "," + filenames[3] + "," + delimiter + "\n");
		out.write(line);
		out.close();
		
	}
}
